using System;
using System.Drawing;
using System.Windows.Forms;
using OutlookPanel;
using TXLooker.WorkItemExtention.UI.OLViewExtension;

namespace TXLooker.WorkItemExtention.Core
{
    /// <summary>
    /// Class that manages nested panel control
    /// </summary>
    public class PanelManager : IDisposable
    {
        private PanelContainer _panelContainer;
        private SubclassedWindow _subclassedSiblingWindow;
        private bool _changingSize;
        private bool show;
        private UserControl _nestedControl;

        public PanelManager(IntPtr parentWindow, IntPtr siblingWindow)
        {
            _parentWindow = parentWindow;
            _siblingWindow = siblingWindow;
        }

        private readonly IntPtr _parentWindow;
        
        public IntPtr ParentWindow
        {
            get { return _parentWindow; }
        }

        private readonly IntPtr _siblingWindow;
        
        public IntPtr SiblingWindow
        {
            get { return _siblingWindow; }
        }
        
        public void Dispose()
        {
            //Dispose the container (if it was initialised)
            if (_panelContainer != null)
                _panelContainer.Dispose();

            //Dispose the subclassing wrapper (if it was initialised)
            if (_subclassedSiblingWindow != null)
                _subclassedSiblingWindow.ReleaseHandle();
        }

        public void ShowBarControl(UserControl nestedControl)
        {
            show = true;
            if (show)
            {
                _nestedControl = nestedControl;
                _panelContainer = new PanelContainer();
                SafeNativeMethods.SetParent(_panelContainer.Handle, ParentWindow);

                ResizePanels();
                //Subclass sibling window to monitor SizeChange event
                try
                {
                    _subclassedSiblingWindow = new SubclassedWindow();
                    _subclassedSiblingWindow.AssignHandle(SiblingWindow);
                    _subclassedSiblingWindow.SizeChanged += subclassedSiblingWindow_SizeChanged;
                }
                catch(Exception e)
                {
                    MessageBox.Show(e.Message);
                }

                _panelContainer.AttachControl(nestedControl);
                _panelContainer.Show();
            }

        }

        public void HideBarControl()
        {
            show = false;
            SafeNativeMethods.SetWindowPos(SiblingWindow, IntPtr.Zero, 0, 0, _panelContainer.Width, _panelContainer.Height, SafeNativeMethods.SWP_NOMOVE | SafeNativeMethods.SWP_NOZORDER);
            SafeNativeMethods.ShowWindow(SiblingWindow, 1);
            _subclassedSiblingWindow.ReleaseHandle();
            _subclassedSiblingWindow.DestroyHandle();
            _panelContainer.Dispose();
            _panelContainer = null;
            _nestedControl = null;
        }
        
        private void ResizePanels()
        {
            if (_changingSize)
                return; //Prevent infinite loops

            _changingSize = true;

            try
            {
                Rectangle siblingRect = SafeNativeMethods.GetWindowRectange(SiblingWindow);

                var topLeft = new SafeNativeMethods.POINT(siblingRect.Left, siblingRect.Top);
                SafeNativeMethods.ScreenToClient(this.ParentWindow, ref topLeft);
                _panelContainer.Width = siblingRect.Width;
                _panelContainer.Left = topLeft.X;
                _panelContainer.Top = topLeft.Y;
                
                _panelContainer.Height = siblingRect.Height;

                _nestedControl.Size = _panelContainer.Size;

                SafeNativeMethods.SetWindowPos(SiblingWindow, IntPtr.Zero, 0, 0, 1, siblingRect.Height, SafeNativeMethods.SWP_NOMOVE | SafeNativeMethods.SWP_NOZORDER);
                // hide outlook grid
                SafeNativeMethods.ShowWindow(SiblingWindow, 0);
            }
            finally
            {
                _changingSize = false;
            }
        }

        private void subclassedSiblingWindow_SizeChanged(object sender, EventArgs e)
        {
            //Since sibling has changed its size, we need to resize both windows again
            if(show)
                ResizePanels();
        }
    }
}